package com.unionpay.resource;

import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.unionpay.rpc.Data;
import com.unionpay.rpc.DataArr;
import com.unionpay.rpc.DataObj;
import com.unionpay.rpc.DataStr;
import com.unionpay.rpc.Rpc;
import com.unionpay.rpc.RpcMethod;
import com.unionpay.util.SHA1;

/**
 * REST接口
 * 
 * @author liuzy
 */
@Path("/old")
@Produces(MediaType.APPLICATION_JSON)
public class Resource {
	/**
	 * 本地账户和余额
	 */
	private static Map<String, Integer> ACCOUNTS = new ConcurrentHashMap<String, Integer>();
	
	/**
	 * 默认账户
	 */
	private static String DEFAULT_ACCOUNT;
	
	/**
	 * RPC账户列表
	 */
	@POST
	@Path("accounts")
	public Response accounts() {
		ArrayList<String> accounts = null;
		RpcMethod method = new RpcMethod(Rpc.ETH_ACCOUNTS);
		Object data = Rpc.request(method);
		if (data instanceof DataArr) {
			accounts = ((DataArr) data).getResult();
			if (accounts != null && !accounts.isEmpty()) {
				DEFAULT_ACCOUNT = accounts.get(0);
				if (ACCOUNTS.isEmpty()) {
					for (String account : accounts) {
						ACCOUNTS.put(account, 0);
					}
				} else {
					for (String account : accounts) {
						if (!ACCOUNTS.containsKey(account)) {
							ACCOUNTS.put(account, 0);
						}
					}
				}
			}
		}
		return render(accounts);
	}

	/**
	 * RPC账户交易
	 */
	@POST
	@Path("putdatatochain")
	public Response putdatatochain(@FormParam("original_address") String original_address, @FormParam("destiny_address") String destiny_address, @FormParam("data") String data) {
		if (data == null || data.isEmpty()) {
			return render("data不能为空");
		}
		if (original_address == null) {
			original_address = DEFAULT_ACCOUNT;
		}
		Data dd = null;
		RpcMethod transMethod = new RpcMethod(Rpc.ETH_SENDTRANSACTION);
		RpcMethod sha3Method = new RpcMethod(Rpc.WEB3_SHA3);
		sha3Method.addParams(data);
		Data cipherData = Rpc.request(sha3Method);
		String ciphertext = null;
		if (cipherData instanceof DataStr) {
			ciphertext = ((DataStr) cipherData).getResult();
		}
		if (ciphertext != null) {
			if (destiny_address == null) {
				transMethod.addParams(original_address, ciphertext);
			} else {
				transMethod.addParams(original_address, destiny_address, ciphertext);
			}
			dd = Rpc.request(transMethod);
			if (dd instanceof DataStr) {
				return render(((DataStr) dd).getResult());
			}
		} else {
			dd = cipherData;
		}
		return render(dd.getError());
	}

	/**
	 * RPC交易查询
	 */
	@POST
	@Path("querydatafromchain")
	public Response querydatafromchain(@FormParam("hash") String hash) {
		if (hash == null || hash.isEmpty()) {
			return render("hash不能为空");
		}
		RpcMethod method = new RpcMethod(Rpc.ETH_GETTRANSACTIONBYHASH);
		method.addParams(hash);
		Data data = Rpc.request(method);
		if (data instanceof DataObj) {
			return render(((DataObj) data).getResult());
		} else {
			return render(data.getError());
		}
	}

	/**
	 * 发币
	 */
	@POST
	@Path("issuetoken")
	public Response issuetoken(@FormParam("quantity") int quantity) {
		if (quantity < 0) {
			return render("quantity必须大于0");
		}
		Data data = null;
		synchronized (ACCOUNTS) {
			if (DEFAULT_ACCOUNT == null || ACCOUNTS.containsKey(DEFAULT_ACCOUNT)) {
				RpcMethod transMethod = new RpcMethod(Rpc.ETH_SENDTRANSACTION);
				RpcMethod sha3Method = new RpcMethod(Rpc.WEB3_SHA3);
				sha3Method.addParams(SHA1.encode(String.format("issue %s %d", DEFAULT_ACCOUNT, quantity)));
				Data cipherData = Rpc.request(sha3Method);
				String ciphertext = null;
				if (cipherData instanceof DataStr) {
					ciphertext = ((DataStr) cipherData).getResult();
				}
				if (ciphertext != null) {
					transMethod.addParams(DEFAULT_ACCOUNT, ciphertext);
					data = Rpc.request(transMethod);
					if (data instanceof DataStr) {
						ACCOUNTS.put(DEFAULT_ACCOUNT, ACCOUNTS.get(DEFAULT_ACCOUNT) + quantity);
						return render(((DataStr) data).getResult());
					}
				} else {
					data = cipherData;
				}
			} else {
				return render("默认account不存在，发币失败");
			}
		}
		return render(data.getError());
	}
	
	/**
	 * 交易
	 */
	@POST
	@Path("sendtoken")
	public Response sendtoken(@FormParam("from") String from, @FormParam("to") String to, @FormParam("amount") int amount) {
		if (amount < 0) {
			return render("amount必须大于0");
		}
		if (from == null) {
			from = DEFAULT_ACCOUNT;
		}
		Data data = null;
		synchronized (ACCOUNTS) {
			if (from == null || ACCOUNTS.containsKey(from)) {
				RpcMethod transMethod = new RpcMethod(Rpc.ETH_SENDTRANSACTION);
				RpcMethod sha3Method = new RpcMethod(Rpc.WEB3_SHA3);
				if (to == null) {// to为空，给from充值
					sha3Method.addParams(SHA1.encode(String.format("issue %s %d", from, amount)));
					Data cipherData = Rpc.request(sha3Method);
					String ciphertext = null;
					if (cipherData instanceof DataStr) {
						ciphertext = ((DataStr) cipherData).getResult();
					}
					if (ciphertext != null) {
						transMethod.addParams(from, ciphertext);
						data = Rpc.request(transMethod);
						if (data instanceof DataStr) {
							ACCOUNTS.put(from, ACCOUNTS.get(from) + amount);
							return render(((DataStr) data).getResult());
						}
					} else {
						data = cipherData;
					}
				} else {// to不为空，from减值 且 to加值
					if (ACCOUNTS.containsKey(to)) {// 集合包含to
						sha3Method.addParams(SHA1.encode(String.format("send from %s to %s %d", from, to, amount)));
						Data cipherData = Rpc.request(sha3Method);
						String ciphertext = null;
						if (cipherData instanceof DataStr) {
							ciphertext = ((DataStr) cipherData).getResult();
						}
						if (ciphertext != null) {
							transMethod.addParams(from, to, ciphertext);
							data = Rpc.request(transMethod);
							if (data instanceof DataStr) {
								int fromBlance = ACCOUNTS.get(from);
								if (fromBlance >= amount) {
									ACCOUNTS.put(from, fromBlance - amount);
									ACCOUNTS.put(to, ACCOUNTS.get(to) + amount);
									return render(((DataStr) data).getResult());
								} else {
									return render("from余额不足，交易失败");
								}
							}
						} else {
							data = cipherData;
						}
					} else {
						return render("to不存在，交易失败");
					}
				}
			} else {
				return render("from不存在，交易失败");
			}
		}
		return render(data.getError());
	}
	
	/**
	 * 查余
	 */
	@POST
	@Path("mybalance")
	public Response mybalance(@FormParam("account") String account) {
		if (account == null || account.isEmpty()) {
			return render(ACCOUNTS);
		}
		for (String key : ACCOUNTS.keySet()) {
			if (key.equals(account)) {
				return render(ACCOUNTS.get(account));
			}
		}
		return render("account不存在");
	}

	public Response render(Object obj) {
		return new Response(obj);
	}

	public class Response {
		private Object data;
		public Response(Object data) {
			this.data = data;
		}
		public Object getData() {
			return data;
		}
		public void setData(Object data) {
			this.data = data;
		}
	}
}